using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using T.FAS.Runtime.Base.Common;
using T.FAS.Runtime.Base.Dao;
using T.FAS.Runtime.Base.Entity;

namespace T.FAS.Runtime.Base.Service
{
    public class FASValidateRuleDevService
    {
        private static readonly FASValidateRuleDevService _instance = new FASValidateRuleDevService();
        private readonly ValidateRuleDao _dao = new ValidateRuleDao();
        public static FASValidateRuleDevService GetInstance()
        {
            return _instance;
        }

        private FASValidateRuleDevService()
        {
        }

        public List<ValidateRule> GetRules(string filter = null)
        {
            try
            {
                string projID = string.Empty;
                if (!string.IsNullOrEmpty(filter))
                {
                    var jObj = JObject.Parse(filter);
                    string projKey = "ProjectID";
                    if (jObj != null && (jObj as IDictionary<string, JToken>).ContainsKey(projKey))
                    {
                        projID = jObj[projKey]?.ToString();
                    }
                }

                return _dao.GetRules(projID);
            }
            catch (Exception e)
            {
                throw new Exception($"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Base_963668345", "获取规则失败! msg:{0}\r\ne:{1}", e.Message,e)}");
            }
        }

        public ValidateRule GetRule(string ruleID)
        {
            try
            {
                return _dao.GetRule(ruleID);
            }
            catch (Exception e)
            {
                throw new Exception($"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Base_1311644682", "获取规则:{0}失败! msg:{1}\r\ne:{2}", ruleID, e.Message,e)}");
            }
        }

        public void DeleteRule(string ruleID)
        {
            try
            {
                _dao.DeleteRule(ruleID);
            }
            catch (Exception e)
            {
                throw new Exception($"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Base_1417323285", "删除规则:{0}失败! msg:{1}\r\ne:{2}", ruleID, e.Message,e)}");
            }
        }

        public void DeleteRules(List<string> ruleIDs)
        {
            try
            {
                _dao.Delete(ruleIDs);
            }
            catch (Exception e)
            {
                throw new Exception($"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Base_520040994", "删除规则:{0}失败! msg:{1}\r\ne:{2}", ruleIDs, e.Message, e)}");
            }
        }

        /// <summary>
        /// 创建或更新
        /// </summary>
        /// <param name = "rule"></param>
        public void CreateOrUpdateRule(ValidateRule rule)
        {
            string userName = UserUtil.GetCurrentUserName();
            rule.LastModifyTime = DateTime.Now;
            rule.LastModifier = userName;
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
                {
                    if (string.IsNullOrEmpty(rule.ID))
                    {
                        rule.ID = Guid.NewGuid().ToString();
                        rule.Creator = userName;
                        rule.CreateTime = DateTime.Now;
                        _dao.Add(new List<object>{rule});
                    }
                    else
                    {
                        _dao.Update(new List<object>{rule});
                    }

                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new Exception($"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Base_1286110121", "新建或者更新规则:{0}失败! msg:{1}\r\ne:{2}",rule?.Name, e.Message, e)}");
            }
        }

        /// <summary>
        /// 创建或更新
        /// </summary>
        /// <param name = "rule"></param>
        public void CreateRule(ValidateRule rule)
        {
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
                {
                    if (string.IsNullOrEmpty(rule.ID))
                    {
                        rule.ID = Guid.NewGuid().ToString();
                    }

                    string userName = UserUtil.GetCurrentUserName();
                    rule.Creator = userName;
                    rule.CreateTime = DateTime.Now;
                    rule.LastModifyTime = DateTime.Now;
                    rule.LastModifier = userName;
                    _dao.Add(new List<object>{rule});
                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new Exception($"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Base_1286110121", "新建或者更新规则:{0}失败! msg:{1}\r\ne:{2}", rule?.Name, e.Message, e)}");
            }
        }

        /// <summary>
        /// 批量创建或更新
        /// </summary>
        /// <param name = "chart"></param>
        public void BatchUpdateValidateRules(List<ValidateRule> rules)
        {
            try
            {
                rules.ForEach(r =>
                {
                    if (r != null)
                        r.Type = ValidateRuleType.Custom;
                }

                );
                var oldDatas = _dao.GetRules();
                Compare(oldDatas, rules, (m, n) => m.ID == n.ID, (m, n) => m.ID == n.ID && m.Name == n.Name && m.OriginRegContent == n.OriginRegContent && m.ErrMsg == n.ErrMsg, out List<ValidateRule> needAdd, out List<ValidateRule> needDelete, out List<ValidateRule> needUpdate);
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
                {
                    _dao.Add(needAdd);
                    _dao.Update(needUpdate);
                    //后续通过批量删除来搞
                    _dao.Delete(needDelete.Select(d => d.ID).ToList());
                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new Exception($"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Base_1449160268", "批量新建或者更新规则失败! msg:{0}\r\ne:{1}", e.Message,e)}");
            }
        }

        /// <summary>
        /// 批量创建或更新
        /// </summary>
        /// <param name = "chart"></param>
        public void BatchDeleteValidateRules(List<string> ruleIDs)
        {
            try
            {
                if (ruleIDs != null && ruleIDs.Count > 0)
                {
                    using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
                    {
                        _dao.Delete(ruleIDs);
                        scope.Complete();
                    }
                }
            }
            catch (Exception e)
            {
                throw new Exception($"{T.ServiceComponent.I18N.Service.TermService.Current.GetTextFormatted("T_FAS_fasr_Base_532035249", "批量删除规则失败! msg:{0}\r\ne:{1}", e.Message, e)}");
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name = "T"></typeparam>
        /// <param name = "oldDatas"></param>
        /// <param name = "newDatas"></param>
        /// <param name = "identifierEqualFunc">判断对象标识是否相等，true:相等，false:不相等</param>
        /// <param name = "bodyEqualFunc">判断对象实体是否相等，true:相等，false:不相等</param>
        /// <param name = "needAdd"></param>
        /// <param name = "needDelete"></param>
        /// <param name = "needUpdate"></param>
        private void Compare<T>(List<T> oldDatas, List<T> newDatas, Func<T, T, bool> identifierEqualFunc, Func<T, T, bool> bodyEqualFunc, out List<T> needAdd, out List<T> needDelete, out List<T> needUpdate)
        {
            if (oldDatas == null)
                oldDatas = new List<T>();
            if (newDatas == null)
                newDatas = new List<T>();
            needAdd = new List<T>();
            needDelete = new List<T>();
            needUpdate = new List<T>();
            List<T> sameDataInOld = new List<T>();
            foreach (T newData in newDatas)
            {
                bool existFlag = false;
                bool changeFlag = false;
                T tmpOldData = default;
                foreach (T oldData in oldDatas)
                {
                    if (identifierEqualFunc(newData, oldData))
                    {
                        changeFlag = !bodyEqualFunc(newData, oldData);
                        tmpOldData = oldData;
                        existFlag = true;
                        break;
                    }
                }

                if (existFlag)
                {
                    sameDataInOld.Add(tmpOldData);
                    if (changeFlag)
                        needUpdate.Add(newData);
                }
                else
                    needAdd.Add(newData);
            }

            needDelete = oldDatas.Where(old => !sameDataInOld.Contains(old)).ToList();
        }
    }
}